package org.zt.ccty.springboot_mybatis_demo.zk;

import org.I0Itec.zkclient.ZkClient;
import org.I0Itec.zkclient.serialize.SerializableSerializer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.zt.ccty.springboot_mybatis_demo.domain.ServiceInfo;
import org.zt.ccty.springboot_mybatis_demo.util.SpringUtil;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Description:
 *
 * @author zhoutao
 * @since 2017/11/27.
 */
public class ZookeeperUtil {

    /**
     * 分割URL的正则表达式
     */
    private static final Pattern KVP_PATTERN = Pattern.compile("([_.a-zA-Z0-9][-_.a-zA-Z0-9]*)[=](.*)");

    /**
     * 应用列表
     */
    private Map<String, List<ServiceInfo>> applicationMap = new TreeMap<>();

    private String env = "230";
    
    private ZkConfig zkConfig;

    public ZookeeperUtil() {
        try {
            readDubboInfo();
        } catch (Exception e) {
            System.out.println("读取Zookeeper的Dubbo配置异常。");
            e.printStackTrace();
        }
    }

    private void readDubboInfo() throws UnsupportedEncodingException {
    	if(zkConfig == null){
    		zkConfig = SpringUtil.getBean(ZkConfig.class);
    	}   	
        String zkAddress = zkConfig.getZKAddress(env);
        ZkClient zkClient = new ZkClient(zkAddress, 10000, 10000, new SerializableSerializer());
        System.out.println("Connected zookeeper ok!");
        List<String> serviceList = zkClient.getChildren("/dubbo");
        System.out.println(serviceList);
        for (String service : serviceList) {
            List<String> urls = zkClient.getChildren("/dubbo/" + service + "/providers");
            if (urls != null && !urls.isEmpty()) {
                for (String url : urls) {
                    url = URLDecoder.decode(url, "UTF-8");
                    String protocol = url.substring(0, url.indexOf("://"));
                    if (protocol.equalsIgnoreCase("dubbo")) {
                        Map<String, String> map = parseKeyValuePair(url, "&");
                        String application = map.get("application");
                        if (application == null || application.length() == 0) {
                            continue;
                        }
                        List<ServiceInfo> serviceInfoList;
                        if (!applicationMap.containsKey(application)) {
                            serviceInfoList = new ArrayList<>();
                            applicationMap.put(application, serviceInfoList);
                        } else {
                            serviceInfoList = applicationMap.get(application);
                        }
                        String interfaceName = map.get("interface");
                        if ("com.smy.smyx.scheduler.service.TaskService".equalsIgnoreCase(interfaceName)) {
                            continue;
                        }
                        List<String> methodList = Arrays.asList(map.get("methods").split(","));
                        ServiceInfo serviceInfo = new ServiceInfo(map.get("interface"), methodList);
                        serviceInfoList.add(serviceInfo);
                    }
                }
            }
        }
        System.out.println("Read dubbo config success.");
    }

    public Map<String, List<ServiceInfo>> getApplicationMap() {
        return this.applicationMap;
    }

    private Map<String, String> parseKeyValuePair(String str, String itemSeparator) {
        String[] tmp = str.split(itemSeparator);
        Map<String, String> map = new HashMap<>(tmp.length);
        for (int i = 0; i < tmp.length; i++) {
            Matcher matcher = KVP_PATTERN.matcher(tmp[i]);
            if (matcher.matches() == false) {
                continue;
            }
            map.put(matcher.group(1), matcher.group(2));
        }
        return map;
    }
}
